spring MVC知识点总结(2) - 注解式控制器

注解式控制器 - 请求映射规则

URL路径限定

普通URL路径映射

@RequestMapping(value={“/test1”, “/user/create”}):多个URL路径可以映射到同一个处理器的功能处理方法。

URI模板模式映射

@RequestMapping(value=”/users/{userId}”):{×××}占位符, 请求的URL可以是 “/users/123456”或”/users/abcd”,通过@PathVariable可以提取URI模板模式中的{×××}中的×××变量

Ant风格的URL路径映射

@RequestMapping(value=”/product?”):可匹配”/product1”或”/producta”,但不匹配”/product”或”/productaa”;

正则表达式风格的URL路径映射

从Spring3.0开始支持正则表达式风格的URL路径映射,格式为{变量名:正则表达式},这样我们就可以通过6.6.5讲的通过@PathVariable提取模式中的{×××:正则表达式匹配的值}中的×××变量了

组合使用URL路径限定,是”或”的关系

如 @RequestMapping(value={“/test1”, “/user/create”})
组合使用是或的关系,即”/test1”或”/user/create”请求URL路径都可以映射到@RequestMapping指定的功能处理方法

请求方法映射限定

//处理器的通用映射前缀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Controller
@RequestMapping("/customers/**")
public class RequestMethodController {
//对类级别的@RequestMapping窄化,表示showForm可处理匹配"/customers/**/create"且请求方法为"GET"的请求;
@RequestMapping(value="/create", method = RequestMethod.GET)
public String showForm() {
System.out.println("===============GET");
return "customer/create";
}
//对类级别的@RequestMapping进行窄化,表示submit可处理匹配"/customers/**/create"且请求方法为"POST"的请求。
@RequestMapping(value="/create", method = RequestMethod.POST)//③类级别的@RequestMapping窄化
public String submit() {
System.out.println("================POST");
return "redirect:/success";
}
}

组合使用请求方法映射限定是”或”的关系

@RequestMapping(value=”/methodOr”, method = {RequestMethod.POST, RequestMethod.GET}):即请求方法可以是 GET 或 POST。

提示

1、一般浏览器只支持GET、POST请求方法,
2、除了GET、POST,还有HEAD、OPTIONS、PUT、DELETE、TRACE。
3、DispatcherServlet默认开启对 GET、POST、PUT、DELETE、HEAD的支持;
4、如果需要支持OPTIONS、TRACE,请添加DispatcherServlet在web.xml的初始化参数:dispatchOptionsRequest 和 dispatchTraceRequest 为true。

请求参数数据映射限定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package cn.javass.chapter6.web.controller.method;
@Controller
@RequestMapping("/customers/**") //①处理器的通用映射前缀
public class RequestMethodController {
@RequestMapping(value="/create", method = RequestMethod.GET)//②类级别的@RequestMapping窄化
public String showForm() {
System.out.println("===============GET");
return "customer/create";
}
@RequestMapping(value="/create", method = RequestMethod.POST)//③类级别的@RequestMapping窄化
public String submit() {
System.out.println("================POST");
return "redirect:/success";
}
}

请求参数数据映射限定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package cn.javass.chapter6.web.controller.parameter;
//省略import
@Controller
@RequestMapping("/parameter1") //①处理器的通用映射前缀
public class RequestParameterController1 {
//表示请求中有"create"的参数名且请求方法为"GET"即可匹配,如可匹配的请求URL"http://×××/parameter1?create"
@RequestMapping(params="create", method=RequestMethod.GET)
public String showForm() {
System.out.println("===============showForm");
return "parameter/create";
}
//表示请求中有"create"的参数名且请求方法为"POST"即可匹配
@RequestMapping(params="create", method=RequestMethod.POST)
public String submit() {
System.out.println("================submit");
return "redirect:/success";
}
}

请求参数中指定参数名 = 值

@RequestMapping(params=”create”, method=RequestMethod.GET)
表示请求中有”create”的参数名且请求方法为”GET”即可匹配,如可匹配的请求URL”http://×××/parameter1?create“

请求参数中指定参数名 != 值

@RequestMapping(params=”submitFlag!=create”, method=RequestMethod.GET)
表示请求中的参数”submitFlag!=create”且请求方法为”GET”即可匹配,如可匹配的请求URL”http://×××/parameter1?submitFlag=abc“

组合使用请求参数名,是”且”的关系

@RequestMapping(params={“test1”, “test2=create”})
表示请求中的有”test1”参数名 且 有”test2=create”参数即可匹配,如可匹配的请求URL”http://×××/parameter3?test1&test2=create"。

请求头数据映射限定

请求头数据中有指定参数名

@RequestMapping(value=”/header/test1”, headers = “Accept”)
表示请求的URL必须为”/header/test1”且请求头中必须有Accept参数才能匹配。

请求头数据中没有指定参数名

@RequestMapping(value=”/header/test2”, headers = “!abc”)
表示请求的URL必须为”/header/test2”且请求头中必须没有abc参数才能匹配。(将Modify Header的abc参数值删除即可)

请求头数据中指定参数名 = 值

@RequestMapping(value=”/header/test3”, headers = “Content-Type=application/json”)
表示请求的URL必须为”/header/test3” 且 请求头中必须有”Content-Type=application/json”参数即可匹配。(将Modify Header的Content-Type参数值改为”application/json”即可)

请求头数据中指定参数名 != 值

@RequestMapping(value=”/header/test7”, headers = “Accept!=text/vnd.wap.wml”)
表示请求的URL必须为”/header/test7” 且 请求头中必须有”Accept”参数但值不等于”text/vnd.wap.wml”即可匹配

组合使用请求头数据:是”且”的关系

@RequestMapping(value=”/header/test8”, headers = {“Accept!=text/vnd.wap.wml”,”abc=123”})
表示请求的URL必须为”/header/test8” 且 请求头中必须有”Accept”参数但值不等于”text/vnd.wap.wml”且 请求中必须有参数”abc=123”即可匹配

注解式控制器 - 生产者消费者限定

基本概念

Media Type

互联网媒体类型,一般就是我们所说的MIME类型,用来确定请求的内容类型或响应的内容类型

常见Media Type:

text/html : HTML格式 text/plain :纯文本格式 text/xml :XML格式
image/gif :gif图片格式 image/jpeg :jpg图片格式 image/png:png图片格式

application/x-www-form-urlencoded :

中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)。
multipart/form-data : 当你需要在表单中进行文件上传时,就需要使用该格式;

application/xhtml+xml :XHTML格式 application/xml : XML数据格式
application/atom+xml :Atom XML聚合格式 application/json : JSON数据格式
application/pdf :pdf格式 application/msword : Word文档格式
application/octet-stream : 二进制流数据(如常见的文件下载)。
Content-Type

内容类型,即请求/响应的内容区数据的媒体类型

请求头的内容类型,表示发送到服务器的内容数据的媒体类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@RequestMapping(value = "/ContentType", method = RequestMethod.GET)
public String showForm() throws IOException {
//form表单,使用application/x-www-form-urlencoded编码方式提交表单
return "consumesproduces/Content-Type";
}
@RequestMapping(value = "/ContentType", method = RequestMethod.POST, headers = "Content-Type=application/x-www-form-urlencoded")
public String request1(HttpServletRequest request) throws IOException {
//1. 得到请求的内容区数据的类型
String contentType = request.getContentType();
System.out.println("========ContentType:" + contentType);
//2. 得到请求的内容区数据的编码方式,如果请求中没有指定则为null
//注意,我们的CharacterEncodingFilter这个过滤器设置了编码(UTF-8)
//编码只能被指定一次,即如果客户端设置了编码,则过滤器不会再设置
String characterEncoding = request.getCharacterEncoding();
System.out.println("========CharacterEncoding:" + characterEncoding);
//3. 表示请求的内容区数据为form表单提交的参数,此时我们可以通过request.getParameter得到数据(key=value)
System.out.println(request.getParameter("realname"));
System.out.println(request.getParameter("username"));
return "success";
}

request中设置请求头”Content-Type: application/x-www-form-urlencoded”表示请求的数据为key/value数据

request功能处理方法:只对请求头为”Content-Type:application/x-www-form-urlencoded”的请求进行处理(即消费请求内容区数据)

request.getContentType():可以得到请求头的内容区数据类型(即Content-Type头的值)
request.getCharacterEncoding():如”Content-Type:application/json;charset=GBK”,则得到的编码为”GBK”,否则如果你设置过滤器(CharacterEncodingFilter)则得到它设置的编码,否则返回null。
request.getParameter():因为请求的内容区数据为application/x-www-form-urlencoded格式的数据,因此我们可以通过request.getParameter()得到相应参数数据。
响应头的内容类型,表示发送到客户端的内容数据类型,和请求头的内容类型类似,只是方向相反

生产者、消费者限定

  1. 功能处理方法是消费者

@RequestMapping(value = “/consumes”, consumes = {“application/json”})
此处使用consumes来指定功能处理方法能消费的媒体类型,其通过请求头的”Content-Type”来判断

此种方式相对使用@RequestMapping的headers = “Content-Type=application/json”更能表明你的目的

  1. 功能处理方法是生产者

@RequestMapping(value = “/produces”, produces = “application/json”)
表示将功能处理方法将生产json格式的数据,此时根据请求头中的Accept进行匹配,如请求头”Accept:application/json”时即可匹配

此种方式相对使用@RequestMapping的headers = “Accept=application/json”更能表明你的目的

  1. 窄化时是覆盖 而 非继承

如类级别的映射为 @RequestMapping(value=”/narrow”, produces=”text/html”),方法级别的为@RequestMapping(produces=”application/xml”),此时方法级别的映射将覆盖类级别的,因此请求头“Accept:application/xml”是成功的,而“text/html”将报406错误码,表示不支持的请求媒体类型

  1. 组合使用生产者、消费者限定是”或”的关系

@RequestMapping(produces={“text/html”, “application/json”}) :将匹配“Accept:text/html”或“Accept:application/json”

  1. 问题

消费的数据,如JSON数据、XML数据都是由我们读取请求的InputStream并根据需要自己转换为相应的模型数据,比较麻烦;

生产的数据,如JSON数据、XML数据都是由我们自己先把模型数据转换为json/xml等数据,然后输出响应流,也是比较麻烦的。

Spring提供了一组注解(@RequestBody、@ResponseBody)和一组转换类(HttpMessageConverter)来完成我们遇到的问题

-------------本文到此结束,感谢您的阅读-------------